package com.y.ari.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.y.ari.common.AriException;
import com.y.ari.common.Constants;
import com.y.ari.common.RestResponse;
import com.y.ari.common.UserHolder;
import com.y.ari.dto.UserDTO;
import com.y.ari.dto.UserFormDto;
import com.y.ari.dto.UserHeadInfoDto;
import com.y.ari.entity.User;
import com.y.ari.mapper.UserMapper;
import com.y.ari.service.UserService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;

import java.util.HashMap;
import java.util.Map;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

/**
 * <p>
 * 用户信息 服务实现类
 * </p>
 *
 * @author yang
 * @since 2023-04-19
 */
@Service
@Slf4j
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {

    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Override
    public String sendMsg(String phone) {
        //生成验证码
        String code = UUID.randomUUID().toString().substring(0, 4);
        //需要将生产的验证码保存到redis中，并且设置有效期
        redisTemplate.opsForValue().set(phone, code, 5, TimeUnit.MINUTES);

        return code;
    }

    /**
     * 校验验证码
     *
     * @return
     */
    public boolean checkCode(String phone, String code) {
        if (StringUtils.isBlank(phone)) {
            AriException.cast("输入错误！");
        }
        String temp = redisTemplate.opsForValue().get(phone).toString();
        if (temp == null) {
            AriException.cast("验证码过期，请重新发送！");
        }
        if (!temp.equals(code)) {
            return false;
        }
        return true;
    }

    /**
     * 修改密码
     *
     * @param userFormDto
     */
    @Transactional
    @Override
    public void changePaw(UserFormDto userFormDto) {
        //如果已登录修改密码，校验手机号是否一致
        UserDTO userDTOH = UserHolder.getUser();
        if (userDTOH != null) {
            User userH = userMapper.selectById(userDTOH.getId());
            if (userH == null) {
                AriException.cast("用户不存在");
            }
            if (!userH.getPhone().equals(userFormDto.getPhone())) {
                AriException.cast("非用户绑定手机号");
            }
        }
        //判断用户是否存在
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, userFormDto.getUsername())
                .or()
                .eq(User::getPhone, userFormDto.getPhone());
        User user = userMapper.selectOne(queryWrapper);
        if (user == null) {
            AriException.cast("用户不存在");
        }


        //修改数据库
        String password = DigestUtils.md5DigestAsHex(userFormDto.getPassword().getBytes());
        user.setPassword(password);
        int i = userMapper.updateById(user);
        if (i == 0) {
            AriException.cast("修改密码失败");
        }

        redisTemplate.delete(userFormDto.getPhone());
    }

    /**
     * 登录
     *
     * @param userFormDto
     * @return
     */
    @Transactional
    @Override
    public String login(UserFormDto userFormDto) {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        if (userFormDto.getUsername() == null && userFormDto.getPhone() != null) {
            boolean b = checkCode(userFormDto.getPhone(), userFormDto.getCode());
            if (!b) {
                AriException.cast("验证码错误");
            }
            //判断用户是否存在

            queryWrapper.eq(User::getPhone, userFormDto.getPhone());
            User user = userMapper.selectOne(queryWrapper);
            if (user == null) {
                AriException.cast("未注册用户");
            }
            //生成token存到redis
            return generateToken(user);
        } else if (userFormDto.getUsername() != null && userFormDto.getPassword() != null) {
            String password = DigestUtils.md5DigestAsHex(userFormDto.getPassword().getBytes());

            //判断用户是否存在
            queryWrapper.eq(User::getUsername, userFormDto.getUsername())
                    .eq(User::getPassword, password);
            User user = userMapper.selectOne(queryWrapper);
            if (user == null) {
                AriException.cast("未注册用户");
            }
            //生成token存到redis
            return generateToken(user);
        }
        return null;
    }

    /**
     * 查询用户名和头像
     *
     * @return
     */
    @Override
    public UserHeadInfoDto selHeadInfo() {
        UserDTO user = UserHolder.getUser();
        if (user == null) {
            return null;
        }
        User userReq = userMapper.selectById(user.getId());
        if (userReq == null) {
            return null;
        }
        UserHeadInfoDto userHeadInfoDto = new UserHeadInfoDto();
        userHeadInfoDto.setUsername(userReq.getUsername());
        userHeadInfoDto.setAvatar(userReq.getAvatar());
        return userHeadInfoDto;
    }

    /**
     * 查询用户信息
     *
     * @param
     * @return
     */
    @Transactional
    @Override
    public UserDTO selUser() {
        UserDTO user = UserHolder.getUser();
        if (user == null) {
            return null;
        }
        User userReq = userMapper.selectById(user.getId());
        if (userReq == null) {
            return null;
        }
        UserDTO userDTO = new UserDTO();
        BeanUtils.copyProperties(userReq, userDTO);
        return userDTO;
    }

    /**
     * 更改用户信息
     *
     * @param userDTO
     * @return
     */
    @Transactional
    @Override
    public UserDTO modifyUser(UserDTO userDTO) {
        User user = new User();
        if (userDTO == null) {
            AriException.cast(Constants.parameter_err);
        }
        BeanUtils.copyProperties(userDTO, user);
        user.setPassword(null);
        user.setUsername(null);
        userMapper.updateById(user);
        UserDTO newUserDTO = selUser();
        return newUserDTO;
    }

    /**
     * 修改手机号
     *
     * @param userFormDto
     */
    @Transactional
    @Override
    public String modifyPhone(UserFormDto userFormDto) {
        //如果已登录，校验手机号是否一致
        UserDTO userDTOH = UserHolder.getUser();
        if (userDTOH == null) {
            AriException.cast("登录状态异常");
        }
        User userH = userMapper.selectById(userDTOH.getId());
        if (userH == null) {
            AriException.cast("登录状态异常");
        }
        if (userH.getPhone().equals(userFormDto.getPhone())) {
            return "验证成功";
        }
        User user = new User();
        user.setId(userDTOH.getId());
        user.setPhone(userFormDto.getPhone());
        int i = userMapper.updateById(user);
        if (i == 0) {
            AriException.cast("修改失败");
        }
        return "修改成功";
    }

    @Override
    public RestResponse modifyAut(UserDTO userDTO) {
        UserDTO userDTOH = UserHolder.getUser();
        User userH = userMapper.selectById(userDTOH.getId());
        if (userH == null) {
            AriException.cast("登录状态异常");
        }
        if (!(StringUtils.isBlank(userH.getName()) && StringUtils.isBlank(userH.getIdNumber()))) {
            return RestResponse.validfail("账号异常");
        }
        User userM = new User();
        userM.setName(userDTO.getName());
        userM.setIdNumber(userDTO.getIdNumber());
        userM.setId(userH.getId());

        int i = userMapper.updateById(userM);
        if (i == 0) {
            return RestResponse.validfail("认证失败");
        }
        return RestResponse.success("认证成功");
    }

    /**
     * 注册用户
     *
     * @param userFormDto
     * @return
     */
    @Transactional
    @Override
    public String signUp(UserFormDto userFormDto) {

        //判断用户是否存在
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(User::getUsername, userFormDto.getUsername())
                .or()
                .eq(User::getPhone, userFormDto.getPhone());
        User user = userMapper.selectOne(queryWrapper);
        if (user != null) {
            AriException.cast("用户已存在");
        }
        //加入数据库
        User newUser = new User();
        BeanUtils.copyProperties(userFormDto, newUser);
        String password = DigestUtils.md5DigestAsHex(newUser.getPassword().getBytes());
        newUser.setPassword(password);

        int insert = userMapper.insert(newUser);
        if (insert == 0) {
            AriException.cast("注册失败");
        }

        //生成token存到redis
        return generateToken(newUser);

    }

    /**
     * 生成token存到redis
     *
     * @param newUser
     * @return
     */
    public String generateToken(User newUser) {
        //保存数据到redis
        //生成token
        String token = UUID.randomUUID().toString();
        UserDTO userDTO = new UserDTO();
        BeanUtils.copyProperties(newUser, userDTO);

        // 将User对象转为HashMap存储
        Map<String, Object> userMap = BeanUtil.beanToMap(userDTO, new HashMap<>(),
                CopyOptions.create().setIgnoreNullValue(false));
        String tokenKey = Constants.LOGIN_USER_KEY + token;

        redisTemplate.opsForHash().putAll(tokenKey, userMap);
        //设置有效期token
        redisTemplate.expire(tokenKey, Constants.LOGIN_USER_TTL, TimeUnit.MINUTES);

        Object temp = redisTemplate.opsForValue().get(userDTO.getPhone());
        if (temp != null) {
            redisTemplate.delete(userDTO.getPhone());
        }
        return token;
    }
}
